#pragma once 
#include "../common/net.hpp"
#include "../common/message.hpp"

namespace yjz_rpc
{
    namespace server
    {
        // 请求方法参数类型
        enum class VTyep
        {
            BOOL,
            INTEGRAL,
            NUMERIC,
            STRING,
            ARRAY,
            OBJECT
        };

        // 收到一个Rpc请求，取出方法名称和参数信息，通过方法名称找到对应服务的描述对象，
        // 进行参数校验，判断都没问题再调用回调函数进行处理
        class ServiceDescribe
        {
        public:
            using ptr = std::shared_ptr<ServiceDescribe>;
            using ParamsDescribe = std::pair<std::string, VTyep>;
            using ServiceCallBack = std::function<void(const Json::Value&, Json::Value&)>;

            ServiceDescribe(VTyep type, std::string&& name, 
                ServiceCallBack&& callback, std::vector<ParamsDescribe>&& desc)
                : _return_type(type), _method_name(std::move(name))
                , _callback(std::move(callback)), _params_desc(std::move(desc))
            {}

            const std::string& method()
            {
                return _method_name;
            }

            bool paramCheck(const Json::Value& params)
            {
                // 对params进行参数校验，判断参数字段是否存在及类型是否一致
                for (auto& desc : _params_desc)
                {
                    if (params.isObject() && params.isMember(desc.first) == false)
                    {
                        LOG(LogLevel::ERROR) << "校验失败，字段缺失！";
                        std::cout << desc.first << std::endl;
                        return false;
                    }
                    if (params.isObject() && check(desc.second, params[desc.first]) == false)
                    {
                        LOG(LogLevel::ERROR) << "参数类型校验失败！";
                        std::cout << desc.first << std::endl;
                        return false;
                    }
                }
                return true;
            }

            bool call(const Json::Value& params, Json::Value& result)
            {
                _callback(params, result);
                if (rTypeCheck(result) == false)
                {
                    LOG(LogLevel::ERROR) << "回调处理函数中的响应信息校验失败！";
                    return false;
                }
                return true;
            }

        private:
            bool rTypeCheck(const Json::Value& val)
            {
                return check(_return_type, val);
            }

            bool check(VTyep type, const Json::Value& val)
            {
                switch (type)
                {
                    case VTyep::BOOL : return val.isBool();
                    case VTyep::INTEGRAL : return val.isIntegral();
                    case VTyep::NUMERIC : return val.isNumeric();
                    case VTyep::STRING : return val.isString();
                    case VTyep::OBJECT : return val.isObject();
                    case VTyep::ARRAY : return val.isArray();
                }
                return false;
            }
        private:
            VTyep _return_type;                         // 结果类型的描述
            std::string _method_name;                   // 方法名称
            ServiceCallBack _callback;                  // 实际的业务回调函数
            std::vector<ParamsDescribe> _params_desc;   // 参数字段的描述
        };

        // 建造者模式
        class ServiceDescirbeFactory
        {
        public:
            void setReturnType(VTyep type)
            {
                _return_type = type;
            }
            void setMethodName(const std::string& name)
            {
                _method_name = name;
            }
            void setCallBack(const ServiceDescribe::ServiceCallBack& callback)
            {
                _callback = callback;
            }
            void setParamsDesc(const std::string& name, VTyep type)
            {
                _params_desc.push_back(std::make_pair(name, type));
            }
            ServiceDescribe::ptr build()
            {
                return std::make_shared<ServiceDescribe>(_return_type, std::move(_method_name), 
                    std::move(_callback), std::move(_params_desc));
            }
        private:
            VTyep _return_type;                                          // 结果类型的描述
            std::string _method_name;                                    // 方法名称
            ServiceDescribe::ServiceCallBack _callback;                  // 实际的业务回调函数
            std::vector<ServiceDescribe::ParamsDescribe> _params_desc;   // 参数字段的描述
        };

        // 用hash_map管理，高效查询
        class ServiceManager
        {
        public:
            using ptr = std::shared_ptr<ServiceManager>;

            void insert(const ServiceDescribe::ptr& desc)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                _services.insert(std::make_pair(desc->method(), desc));
            }

            ServiceDescribe::ptr select(const std::string& name)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                auto it = _services.find(name);
                if (it == _services.end())
                {
                    return ServiceDescribe::ptr();
                }
                return it->second;
            }

            void remove(const std::string& name)
            {
                std::unique_lock<std::mutex> lock(_mutex);
                _services.erase(name);
            }
        private:
            std::mutex _mutex;
            std::unordered_map<std::string, ServiceDescribe::ptr> _services;
        };

        class RpcRouter
        {
        public:
            using ptr = std::shared_ptr<RpcRouter>;

            RpcRouter()
                : _service_manager(std::make_shared<ServiceManager>())
            {}

            // 注册到Dispatcher模块针对Rpc请求进行回调处理的业务函数
            void onRpcRequest(const BaseConnection::ptr& conn, RpcRequest::ptr& request)
            {
                // 1.查询客户端请求的方法描述，判断当前服务端是否能提供对应的服务
                auto service = _service_manager->select(request->method());
                if (service.get() == nullptr)
                {
                    LOG(LogLevel::ERROR) << "未找到该服务！";
                    std::cout << request->method() << std::endl;
                    response(conn, request, Json::Value(), RCode::RCODE_NOT_FOUND_SERVICE);
                    return;
                }
                // 2.进行参数校验，进一步确定能否提供服务
                if (service->paramCheck(request->params()) == false)
                {
                    LOG(LogLevel::ERROR) << "参数校验失败！";
                    std::cout << request->method() << std::endl;
                    response(conn, request, Json::Value(), RCode::RCODE_INVALID_PARAMS);
                    return;
                }
                // 3.调用业务回调接口进行业务处理
                Json::Value result;
                bool res = service->call(request->params(), result);
                if (res == false)
                {
                    LOG(LogLevel::ERROR) << "响应信息校验失败！";
                    std::cout << request->method() << std::endl;
                    response(conn, request, Json::Value(), RCode::RCODE_INTERNAL_ERROR);
                    return;
                }
                // 4.处理完毕得到结果，组织响应，发送给客户端
                response(conn, request, result, RCode::RCODE_OK);
                return;
            }

            // 提供给用户进行注册服务
            void registerMethod(const ServiceDescribe::ptr& service)
            {
                _service_manager->insert(service);
            }
        private:
            void response(const BaseConnection::ptr& conn, const RpcRequest::ptr& req, 
                const Json::Value& res, RCode rcode)
            {
                auto msg = MessageFactory::create<RpcResponse>();
                msg->setId(req->getId());
                msg->setMType(yjz_rpc::MType::RSP_RPC);
                msg->setRcode(rcode);
                msg->setResult(res);
                conn->send(msg);
            }
        private:
            ServiceManager::ptr _service_manager;
        };
    }
}